package com.vhall.component.framework.oss.client.impl.alicloud;

import cn.hutool.core.lang.Assert;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectResult;
import com.vhall.component.framework.oss.client.OssResult;
import com.vhall.component.framework.oss.client.impl.AbstractOssClient;
import com.vhall.component.framework.oss.properties.OssProperties;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

/**
 * 阿里云 OSS 实现
 *
 * @author yongzheng.xu
 * @date 2021/5/22 21:47
 */
@Slf4j
public class AliCloudClient extends AbstractOssClient {


    /**
     * 阿里云客户端
     */
    private volatile OSSClient client;


    public AliCloudClient(OssProperties properties) {
        super(properties, new AliCloudCodeMapping());
        Assert.notEmpty(properties.getAppId(), "secretId 不能为空");
        Assert.notEmpty(properties.getSecretKey(), "secretKey 不能为空");
    }

    @Override
    protected void doInit() {
        client = new OSSClient(properties.getFullRegion(), properties.getAppId(), properties.getSecretKey());
    }

    @Override
    protected OssResult<String> doUpload(String name, String contentType, InputStream stream) throws IOException {

        try {
            String prefix = properties.getPrefix();
            String bucket = properties.getBucket();
            //创建上传Object的Metadata
            ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentLength(stream.available());
            objectMetadata.setCacheControl("no-cache");
            objectMetadata.setHeader("Pragma", "no-cache");
            objectMetadata.setContentType(contentType);
//            objectMetadata.setContentDisposition("inline;filename=" + name);
            objectMetadata.setContentDisposition("attachment;filename=\"" + URLEncoder.encode(name, String.valueOf(StandardCharsets.UTF_8)) + "\"");

            // 指定上传文件操作时是否覆盖同名Object。
            // 不指定x-oss-forbid-overwrite时，默认覆盖同名Object。
            // 指定x-oss-forbid-overwrite为false时，表示允许覆盖同名Object。
            // 指定x-oss-forbid-overwrite为true时，表示禁止覆盖同名Object，如果同名Object已存在，程序将报错。
            objectMetadata.setHeader("x-oss-forbid-overwrite", "false");
            String objectName = prefix + "/" + name;
            //上传文件
            PutObjectResult result = client.putObject(bucket, objectName, stream, objectMetadata);

            String url = "https://" + bucket + "." + properties.getFullRegion() + "/" + objectName;
            String cdnRegion = properties.getCdnRegion();
            if (org.apache.commons.lang3.StringUtils.isNotBlank(cdnRegion)) {
                url = "https://" + properties.getCdnRegion() + "/" + objectName;
            }
            return OssResult.build("OK", "success", result.getRequestId(), url, codeMapping);
        } catch (OSSException ex) {
            log.error("上传AliOSS失败:", ex);
            return OssResult.build(ex.getErrorCode(), ex.getErrorMessage(), ex.getRequestId(), "", codeMapping);

        } catch (ClientException ex) {
            return OssResult.build(ex.getErrorCode(), ex.getErrorMessage(), ex.getRequestId(), "", codeMapping);

        }
    }
}
